package com.zenithmind.library.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;

import com.zenithmind.common.config.AuthInterceptorConfig;

import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;

/**
 * 图书管理服务安全配置
 * 统一管理认证拦截器和Spring Security的跳过路径配置
 */
@Slf4j
@Configuration
@EnableWebSecurity
public class LibrarySecurityConfig {

    // OpenAPI endpoints
    private static final String[] AUTH_WHITELIST = {
        // SpringDoc OpenAPI endpoints
        "/v3/api-docs/**",
        "/swagger-ui/**",
        "/swagger-ui.html",
        "/doc.html",
        "/webjars/**",
        // Knife4j endpoints
        "/favicon.ico",
        "/knife4j/**",
        "/knife4j-ui/**",
        "/knife4j.html"
    };

    /**
     * 公开端点配置 - 统一管理认证拦截器和Spring Security的跳过路径
     * 开发者可以在这里统一配置所有需要跳过认证的端点
     */
    public static final String[] PUBLIC_ENDPOINTS = {
        // 图书公开查询端点 - 允许游客浏览
        "/api/zenithMind/book/public/**",
        "/api/zenithMind/book/search",
        "/api/zenithMind/book/categories",
        "/api/zenithMind/book/popular",
        "/api/zenithMind/book/latest",
        "/api/zenithMind/book/*/preview",
        // 图书分类公开端点
        "/api/zenithMind/book-category/public/**",
        "/api/zenithMind/book-category/tree",
        // 借阅记录公开统计端点
        "/api/zenithMind/borrow-record/statistics/public",
        // 健康检查和其他公开端点
        "/actuator/**",
        "/health",
        "/info"
    };
    
    // 需要用户角色的端点
    private static final String[] USER_ENDPOINTS = {
        "/api/zenithMind/book/**",
        "/api/zenithMind/book-category/**",
        "/api/zenithMind/borrow-record/**"
    };
    
    // 需要图书管理员角色的端点
    private static final String[] LIBRARIAN_ENDPOINTS = {
        "/api/zenithMind/book/create",
        "/api/zenithMind/book/*/edit",
        "/api/zenithMind/book/*/delete",
        "/api/zenithMind/book/*/inventory",
        "/api/zenithMind/book-category/create",
        "/api/zenithMind/book-category/*/edit",
        "/api/zenithMind/book-category/*/delete",
        "/api/zenithMind/borrow-record/*/approve",
        "/api/zenithMind/borrow-record/*/return"
    };
    
    // 需要管理员角色的端点
    private static final String[] ADMIN_ENDPOINTS = {
        "/api/zenithMind/book/admin/**",
        "/api/zenithMind/book-category/admin/**",
        "/api/zenithMind/borrow-record/admin/**",
        "/api/zenithMind/manage/**"
    };

    /**
     * 图书管理服务安全配置
     * 自行管理认证和授权
     */
    @Bean
    @Order(1)
    public SecurityFilterChain librarySecurityFilterChain(HttpSecurity http) throws Exception {
        
        http
            // 禁用CSRF保护
            .csrf(AbstractHttpConfigurer::disable)
            // 配置认证和授权规则
            .authorizeHttpRequests(authorize -> {
                // 明确允许API文档相关端点
                authorize.requestMatchers(AUTH_WHITELIST).permitAll();
                // 允许公开端点 - 使用统一配置
                authorize.requestMatchers(PUBLIC_ENDPOINTS).permitAll();
                // 图书管理员角色端点
                authorize.requestMatchers(LIBRARIAN_ENDPOINTS).hasAnyRole("LIBRARIAN", "ADMIN");
                // 用户角色端点
                authorize.requestMatchers(USER_ENDPOINTS).authenticated();
                // 管理员角色端点
                authorize.requestMatchers(ADMIN_ENDPOINTS).hasRole("ADMIN");
                // 其他请求需要认证
                authorize.anyRequest().authenticated();
            })
            // 使用无状态会话
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            // 禁用OAuth2资源服务器功能
            .oauth2ResourceServer(AbstractHttpConfigurer::disable);
        
        return http.build();
    }

    /**
     * 配置认证拦截器的跳过路径
     * 使用统一的PUBLIC_ENDPOINTS配置，确保Spring Security和认证拦截器使用相同的跳过路径
     * 通过BeanPostProcessor在Bean创建后设置跳过路径
     */
    @Bean
    public BeanPostProcessor libraryAuthPropertiesPostProcessor() {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof AuthInterceptorConfig.AuthProperties && "authProperties".equals(beanName)) {
                    AuthInterceptorConfig.AuthProperties properties = (AuthInterceptorConfig.AuthProperties) bean;
                    properties.setSkipPaths(Arrays.asList(PUBLIC_ENDPOINTS));
                    log.info("已为图书管理服务认证拦截器设置统一的跳过路径配置，路径数量: {}", PUBLIC_ENDPOINTS.length);
                }
                return bean;
            }
        };
    }
}
